package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zzyl.base.PageResponse;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.exception.BusinessException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * 设备
 */
@Slf4j
@Service
public class DeviceServiceImpl extends ServiceImpl<DeviceMapper, Device> implements DeviceService {

    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;

    @Autowired
    private Client client;

    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    public void syncProductList() {
        log.info("==========同步产品列表开始==========");
        int page=1;
        while (true){
            //填充请求参数
            QueryProductListRequest request = new QueryProductListRequest();
            request.setCurrentPage(page++);
            request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            request.setPageSize(20);

            QueryProductListResponse response;
            //调用客户端查询产品列表
            try {
                response = client.queryProductList(request);
            } catch (Exception e) {
                throw new BusinessException("产品列表查询失败");
            }

            //判断 如果查询结果为空 说明全部查询完毕 跳出死循环
            if (CollectionUtil.isEmpty(response.getBody().getData().getList().getProductInfo())){
                log.info("==========同步产品列表结束==========");
                break;
            }

            //封装数据
            List<ProductVo> productVoList = response.getBody().getData().getList().getProductInfo().stream().map(productInfo ->
                    BeanUtil.copyProperties(productInfo, ProductVo.class)
            ).collect(Collectors.toList());

            //多次同步时 清空之前的缓存 防止每次的缓存堆积起来
            if (page==2){
                redisTemplate.delete("PRODUCT_LIST");
            }

            //把获取到的数据保存到redis中
            redisTemplate.opsForList().leftPushAll("PRODUCT_LIST", productVoList);

        }
    }

    @Override
    public List<ProductVo> findAllProduct() {
        return redisTemplate.opsForList().range("PRODUCT_LIST", 0, -1);
    }

    @Override
    public void registerDevice(DeviceDto deviceDto) {
        //1. 检查设备是否存在
        LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Device::getDeviceName, deviceDto.getDeviceName());
        Long count = getBaseMapper().selectCount(wrapper);
        if (count > 0) {
            throw new BusinessException("设备已存在");
        }
        //2. 向IOT新增设备
        //给request赋值
        RegisterDeviceRequest request = deviceDto.getRegisterDeviceRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        //存入
        RegisterDeviceResponse response=null;
        try {
            response= client.registerDevice(request);
        } catch (Exception e) {
            throw new BusinessException("设备注册失败");
        }
        //判断接口是否调通

        //3. 准备向数据库保存的数据
        Device device = BeanUtil.copyProperties(deviceDto, Device.class);
        device.setIotId(response.getBody().getData().getIotId());
        String productName = findAllProduct().stream().filter(productVo ->
            StrUtil.equals(productVo.getProductKey(), deviceDto.getProductKey())
        ).findFirst().get().getProductName();
        device.setProductName(productName);
        //如果设备绑定的位置是随身设备，则把物理绑定位置设置为-1
        if (device.getLocationType()==0){
            device.setPhysicalLocationType(-1);
        }
        //4. 保存设备数据到数据库
        try {
            getBaseMapper().insert(device);
        }catch (Exception e){
            try {
                DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
                deleteDeviceRequest.setDeviceName(device.getDeviceName());
                deleteDeviceRequest.setIotId(device.getIotId());
                deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
                deleteDeviceRequest.setProductKey(device.getProductKey());
                client.deleteDevice(deleteDeviceRequest);
            } catch (Exception exception) {
                throw new BusinessException("向IOT注册失败");
            }
        }
    }

    @Override
    public PageResponse<Device> findByPage(DevicePageQueryDto devicePageQueryDto) {
        //1. 设置分页条件
        Page<Device> page = new Page<>(devicePageQueryDto.getPageNum(), devicePageQueryDto.getPageSize());
        //2. 设置查询条件
        LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(StrUtil.isNotEmpty(devicePageQueryDto.getProductKey()), Device::getProductKey, devicePageQueryDto.getProductKey())
                .eq(devicePageQueryDto.getLocationType() != null, Device::getLocationType, devicePageQueryDto.getLocationType())
                .like(StrUtil.isNotEmpty(devicePageQueryDto.getDeviceName()), Device::getDeviceName, devicePageQueryDto.getDeviceName())
                .orderByDesc(Device::getCreateTime);

        //3. 执行查询
        page = getBaseMapper().selectPage(page, wrapper);

        //4. 查询创建人
        page.getRecords().stream().forEach(e->e.setCreator("超级管理员"));

        return new PageResponse<>(page);
    }

    //查看设备明细
    @Override
    public DeviceVo queryDeviceDetail(QueryDeviceDetailRequest request) {
        //去阿里云查询设备明细
        QueryDeviceDetailResponse response;
        try {
            response = client.queryDeviceDetail(request);
        } catch (Exception e) {
            throw new BusinessException("物联网查询设备失败");
        }
        response.getBody().getData();

        //去数据库查询设备明细
        LambdaQueryWrapper<Device> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Device::getIotId, request.getIotId());
        Device device = getBaseMapper().selectOne(wrapper);

        //拼接
        DeviceVo deviceVo = BeanUtil.copyProperties(device, DeviceVo.class);
        BeanUtil.copyProperties(response.getBody().getData(), deviceVo, CopyOptions.create().ignoreNullValue());

        return deviceVo;
    }

    //修改设备
    @Override
    public void updateDevice(DeviceDto deviceDto) {
        //将阿里云端数据删除并重建'
        //删除
        DeleteDeviceRequest deleteDeviceRequest=new DeleteDeviceRequest();
        deleteDeviceRequest.setDeviceName(deviceDto.getDeviceName());
        deleteDeviceRequest.setIotId(deviceDto.iotId);
        deleteDeviceRequest.setProductKey(deviceDto.productKey);
        deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        DeleteDeviceResponse deleteDeviceResponse;
        try {
            deleteDeviceResponse = client.deleteDevice(deleteDeviceRequest);
        } catch (Exception e) {
            throw new BusinessException("物联网删除失败");
        }

        //新增
        RegisterDeviceRequest request = deviceDto.getRegisterDeviceRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        //存入
        RegisterDeviceResponse response=null;
        try {
            response= client.registerDevice(request);
        } catch (Exception e) {
            throw new BusinessException("设备注册失败");
        }

        //直接修改数据库
        Device device = BeanUtil.copyProperties(deviceDto, Device.class);
        getBaseMapper().updateById(device);
    }

    //删除设备
    @Override
    public void delete(QueryDeviceDetailRequest request) {
        DeviceVo deviceVo = queryDeviceDetail(request);
        //删除iot
        DeleteDeviceRequest deleteDeviceRequest=new DeleteDeviceRequest();
        deleteDeviceRequest.setDeviceName(deviceVo.getDeviceName());
        deleteDeviceRequest.setIotId(deviceVo.getIotId());
        deleteDeviceRequest.setProductKey(deviceVo.productKey);
        deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        try {
            client.deleteDevice(deleteDeviceRequest);
        } catch (Exception e) {
            throw new BusinessException("IOT删除失败");
        }

        //删除数据库
        getBaseMapper().deleteById(deviceVo);
    }
}
